package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.xbongbong.lfasr.util.StringUtil;
import com.xbongbong.paas.enums.ScoreConditionEnum;
import com.xbongbong.paas.enums.clazz.ConditionClass;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.pojo.dto.ConditionListDTO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.redis.RedisTimeConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.pro.domain.entity.ScoreRangeConditionEntity;
import com.xbongbong.pro.domain.entity.ScoreRangeEntity;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ScoreErrorCodeEnum;
import com.xbongbong.pro.score.pojo.dto.ScoreRangeDetailDTO;
import com.xbongbong.pro.score.pojo.dto.ScoreRangeSaveDTO;
import com.xbongbong.pro.score.pojo.vo.ScoreRangeConditionListVO;
import com.xbongbong.pro.score.pojo.vo.ScoreRangeDetailVO;
import com.xbongbong.saas.enums.ScoreShowTypeEnum;
import com.xbongbong.saas.help.ScoreRuleHelp;
import com.xbongbong.saas.model.ScoreRangeModel;
import com.xbongbong.saas.service.ScoreRangeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;


/**
 * 评分显示区间实现类
 *
 * @author chunyang.qin
 * @version v1.0
 * @date 2020/12/2 10:35
 * @since v1.0
 */
@Service("ScoreRangeService")
public class ScoreRangeServiceImpl implements ScoreRangeService {

    private static final Logger LOG = LoggerFactory.getLogger(ScoreRangeServiceImpl.class);

    @Resource
    private ScoreRuleHelp scoreRuleHelp;
    @Resource
    private ScoreRangeModel soScoreRangeModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;

    //启用
    private static Integer ENABLE = 1;

    //禁用
    private static Integer DISABLE = 0;

    @Override
    public ScoreRangeDetailVO getScoreRange(ScoreRangeDetailDTO scoreRangeDetailDTO) throws XbbException {
        return soScoreRangeModel.getScoreRange(scoreRangeDetailDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseVO saveScoreRange(ScoreRangeSaveDTO scoreRangeSaveDTO) throws XbbException {
        BaseVO baseVO = new BaseVO();
        Integer scoreShowType = scoreRangeSaveDTO.getScoreShowType();
        Long formId = scoreRangeSaveDTO.getFormId();
        String corpid = scoreRangeSaveDTO.getCorpid();
        //查询一下就的评分规则，用于对比是新增还是编辑
        ScoreRangeEntity oldRange = soScoreRangeModel.getByFormId(formId, corpid);

        //如果是展示范围
        if (scoreShowType.equals(ScoreShowTypeEnum.RANGE.getCode())) {
            //常规校验
            validateAddScoreRange(scoreRangeSaveDTO);
            ScoreRangeEntity packageScoreRangeEntity = scoreRuleHelp.packageScoreRangeEntity(scoreRangeSaveDTO);
            if (Objects.nonNull(oldRange)) {
                packageScoreRangeEntity.setId(oldRange.getId());
                soScoreRangeModel.update(packageScoreRangeEntity);
            } else {
                //新增
                soScoreRangeModel.insert(packageScoreRangeEntity);
            }
            //刷新缓存
            setScoreScreenItems2Redis(formId,scoreRangeSaveDTO.getScoreRangeList());
        } else {
            //展示的是分值,查询一下该表单下是否已经有设置过是"启用"状态的区间展示，有的话，把启用改为禁用
            if (Objects.nonNull(oldRange) && ENABLE.equals(oldRange.getEnable())) {
                oldRange.setEnable(DISABLE);
                soScoreRangeModel.update(oldRange);
            }
        }
        //校验范围展示
        return baseVO;
    }

    /**
     * 评分区间是“区间”方式展示时，获取评分筛选项下拉框的值
     * @param corpid
     * @param formId
     * @return
     * @throws XbbException
     */
    @Override
    public List<ItemPoJo> getItems4ScoreRangeScreen(String corpid , Long formId) throws XbbException {
        List<ItemPoJo> itemPoJos = null;
        //先从缓存中读取
        String value = paasRedisHelper.getValue(RedisPrefixConstant.SCORE_RANGE_SCREEN, String.valueOf(formId));
        if(StringUtil.isEmpty(value)){
            //缓存中没有，读取一遍数据库
            ScoreRangeDetailVO scoreRange = getScoreRange(new ScoreRangeDetailDTO(corpid,formId));
            //返回结果，并且重新刷新缓存
            itemPoJos =  setScoreScreenItems2Redis(formId,scoreRange.getScoreRangeList());
        }else{
            //直接从缓存中读取
            itemPoJos = JSONArray.parseArray(value, ItemPoJo.class);
        }
        return itemPoJos;
    }

    /**
     * 把评分区间转为 下拉框值 缓存起来
     * @param formId
     * @param scoreRangeList
     * @return
     */
    private List<ItemPoJo> setScoreScreenItems2Redis(Long formId,List<ScoreRangeConditionEntity> scoreRangeList){
        List<ItemPoJo> itemPoJos = null;
        try {
            if (CollectionsUtil.isNotEmpty(scoreRangeList)) {
                itemPoJos = new ArrayList<>();
                ItemPoJo itemPoJo;
                //下标当code
                for (int i = 0; i < scoreRangeList.size(); i++) {
                    ScoreRangeConditionEntity scoreRangeConditionEntity = scoreRangeList.get(i);
                    itemPoJo = new ItemPoJo(scoreRangeConditionEntity.getShowValue(),i);
                    itemPoJos.add(itemPoJo);
                }
                //评分区间筛选items缓存，时间为24小时
                paasRedisHelper.setValue(RedisPrefixConstant.SCORE_RANGE_SCREEN, formId.toString(), JSON.toJSONString(itemPoJos), RedisTimeConstant.LONG_DURATION);
            }
        } catch (Exception exception) {
            LOG.error("setScoreScreenItems2Redis 写入redis 异常{}", exception.getMessage());
        }
        return itemPoJos;
    }

    private void validateAddScoreRange(ScoreRangeSaveDTO scoreRangeSaveDTO) throws XbbException {
        if (Objects.nonNull(scoreRangeSaveDTO)) {
            List<ScoreRangeConditionEntity> scoreRangeList = scoreRangeSaveDTO.getScoreRangeList();
            if (CollectionsUtil.isNotEmpty(scoreRangeList)) {
                for (ScoreRangeConditionEntity scoreRangeConditionEntity : scoreRangeList) {
                    //如果是范围的话， 左边的值是要小于 右边的值
                    if (Objects.equals(scoreRangeConditionEntity.getSymbol(), ScoreConditionEnum.RANGE.getSymbol())) {
                        List<Object> value = scoreRangeConditionEntity.getValue();
                        //条件是区间时，右边的值小于等于左边的值，要和列表筛选 左小右大 保持一致
                        if(((Number)value.get(1)).doubleValue() <= ((Number)value.get(0)).doubleValue()){
                            throw new XbbException(ScoreErrorCodeEnum.API_ERROR_1200019, ScoreErrorCodeEnum.API_ERROR_1200019.getMsg());
                        }
                    }
                }
            }
        }
    }

    @Override
    public ScoreRangeConditionListVO getScoreRangeCondition(ConditionListDTO conditionListDTO) throws XbbException {
        ScoreRangeConditionListVO scoreRangeConditionListVO = new ScoreRangeConditionListVO();
        List<ConditionClass> scoreRangeConditionList = scoreRuleHelp.getScoreRangeConditionList();
        scoreRangeConditionListVO.setConditionList(scoreRangeConditionList);
        return scoreRangeConditionListVO;
    }
}
